/**
 * 存放worker的代码,大型计算防止主线程卡顿
 * */
// 顶部事件轴canvas的绘制
const workerCode = () => {
  const configObj = {
    width: 0,
    height: 0,
    times: 0,
    timeScale: 0,
    marginRight: 0, // 最后一个有距离
  };
  function workerRenderFunc() {
    const { times, timeScale, width, height, marginRight } = configObj;
    const canvas = new OffscreenCanvas(width, height);
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, width, height);
    let curLeft = 0;
    let barHeight;
    let textWidth;
    const BAR_LEFT = (width - marginRight - 1) / (times - 1) - 1;
    const BAR_WIDTH = 1;
    const BAR_COLOR = 'rgba(255,255,255,.25)';
    const BAR_HEIGHT = 6;
    const BAR_TEXT_HEIGHT = 10;
    const TEXT_COLOR = 'rgba(255,255,255,.65)';
    const TEXT_HEIGHT = 10;
    const SHORT_TEXT_WIDTH = 12;
    const LONG_TEXT_WIDTH = 18;
    for (let i = 0; i < times; i++) {
      // 判断一下是否需要展示文字
      const item = timeScale[i];
      barHeight = item.timeText ? BAR_TEXT_HEIGHT : BAR_HEIGHT;
      ctx.fillStyle = BAR_COLOR;
      ctx.fillRect(curLeft, 0, BAR_WIDTH, barHeight);
      // 绘制文字
      if (item.timeText) {
        textWidth = item.timeText.length === 5 ? SHORT_TEXT_WIDTH : LONG_TEXT_WIDTH;
        ctx.font = '10px';
        ctx.fillStyle = TEXT_COLOR;
        // 解决文字超出区域不显示的问题
        let textX = curLeft - textWidth;
        i === 0 && (textX = curLeft);
        if (i === times - 1 || i === times - 2) {
          const paddingWidth = i === times - 1 ? 2 : -5;
          textX = curLeft - textWidth * 2 - paddingWidth;
        }
        const textY = barHeight + TEXT_HEIGHT;
        ctx.fillText(item.timeText, textX, textY);
      }
      curLeft += BAR_WIDTH + BAR_LEFT;
    }
    return canvas;
  }
  onmessage = e => {
    Object.assign(configObj, e.data);
    const canvas = workerRenderFunc();
    postMessage(canvas.transferToImageBitmap());
  };
};
let code = workerCode.toString();
code = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'));
const blob = new Blob([code], { type: 'application/javascript' });
export const scaleCanvas = URL.createObjectURL(blob);

// 背景音乐canvas绘制
const workerCode1 = () => {
  const configObj = {
    renderArr: [],
    width: 0,
    height: 0,
    pixel: 1,
  };
  function workerRenderFunc() {
    const { renderArr, width, height, pixel } = configObj;
    const canvas = new OffscreenCanvas(width, height);
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, width, height);
    // 创建一个渐变色
    const gradient = ctx.createLinearGradient(0, height, 0, 0);
    gradient.addColorStop(0, '#22785f');
    gradient.addColorStop(0.45, '#22785f');
    gradient.addColorStop(0.45, '#AB973C');
    gradient.addColorStop(0.75, '#AB973C');
    gradient.addColorStop(0.75, '#b64b43');
    gradient.addColorStop(0.95, '#b64b43');
    const MARGIN_LEFT = pixel;
    const BAR_WIDTH = 3 * pixel; // 计算每一个柱形+空白区域的宽度-空白区域
    let curLeft = 0;
    for (let i = 0; i < renderArr.length; i++) {
      const item = renderArr[i];
      ctx.fillStyle = gradient;
      ctx.fillRect(curLeft, height - item, BAR_WIDTH, item);
      curLeft += BAR_WIDTH + MARGIN_LEFT;
      if (curLeft > width) {
        break;
      }
    }
    return canvas;
  }
  onmessage = e => {
    Object.assign(configObj, e.data);
    const canvas = workerRenderFunc();
    postMessage(canvas.transferToImageBitmap());
  };
};
let code1 = workerCode1.toString();
code1 = code1.substring(code1.indexOf('{') + 1, code1.lastIndexOf('}'));
const blob1 = new Blob([code1], { type: 'application/javascript' });
export const musicCanvas = URL.createObjectURL(blob1);

// 背景音乐的频谱图
const workerCode2 = () => {
  const configObj = {
    width: 0, // 绘制的宽度
    renderWidth: 4, // 绘制的宽度
    maxHeight: 0, // 最大高度
    musicSrc: 0, // 音乐地址,可空
    audioArrayBuffer: null,
  };
  // 下载二进制
  function getBlobByUrl(url) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.responseType = 'arraybuffer';
      xhr.onload = () => {
        resolve(xhr.response);
      };
      xhr.onerror = e => {
        reject(e);
      };
      xhr.send();
    });
  }
  // 计算柱状图
  async function calcColumns() {
    const { width, maxHeight, musicSrc, audioArrayBuffer } = configObj;
    try {
      const num = calcColumnsNum(width, configObj.renderWidth);
      const audioAB = musicSrc ? await getBlobByUrl(musicSrc) : audioArrayBuffer;
      const splitArr = splitAudio(audioAB, num);
      return calcRMS(splitArr, maxHeight); // 拿到切割好的数组之后计算每一个段的平均值
    } catch (e) {
      console.log(e);
    }
  }
  function splitAudio(buffer, num) {
    const uintBuffer = new Uint8Array(buffer); // 转为无符号
    const splitLength = Math.floor(uintBuffer.byteLength / num); // 一份的长度
    const res = [];
    let startIndex = 0;
    let endIndex = splitLength;
    for (let i = 0; i < num; i++) {
      res.push(uintBuffer.slice(startIndex, endIndex));
      startIndex = endIndex;
      endIndex = startIndex + splitLength;
    }
    // 这里最后一份的数据不需要了
    return res;
  }
  // 计算每一数组的RMS值
  function calcRMS(splitArr, maxHeight) {
    const arr1 = [];
    const arr2 = [];
    const res = [];
    splitArr.forEach(item => {
      const energy = calcAvg(item);
      arr1.push(energy);
    });
    const arr3 = deleteMinAndMAx(arr1);
    const maxValue1 = Math.max(...arr3); // 最大能量值
    arr3.forEach(item => {
      arr2.push(maxValue1 - item);
    });
    const maxValue2 = Math.max(...arr2); // 最大差值,最小能量为0
    arr2.forEach(item => {
      res.push(((maxValue2 - item) / maxValue2) * maxHeight);
    });
    return res;
  }
  // 计算平均值
  function calcAvg(buffer) {
    let sum = 0;
    for (let i = 0; i < buffer.length; i++) {
      sum += buffer[i];
    }
    return sum / buffer.length;
  }
  // 删除最大值和最小值,减少误差
  function deleteMinAndMAx(arr) {
    const min = Math.min(...arr);
    const res = [];
    arr.forEach(item => {
      if (item !== min) {
        res.push(item);
      }
    });
    return res;
  }
  // 计算当前宽度可以容纳多少柱形
  function calcColumnsNum(width, minWidth) {
    return Math.floor(width / minWidth);
  }
  onmessage = e => {
    Object.assign(configObj, e.data);
    calcColumns().then(res => {
      postMessage(res);
    });
  };
};
let code2 = workerCode2.toString();
code2 = code2.substring(code2.indexOf('{') + 1, code2.lastIndexOf('}'));
const blob2 = new Blob([code2], { type: 'application/javascript' });
export const calcSpectrum = URL.createObjectURL(blob2);

// 文本驱动轴文字的绘制
const workerCode3 = () => {
  const configObj = {
    sliderArr: [], // 里面包含每一块的地址
  };
  // 计算柱状图
  function calcText() {
    const { sliderArr } = configObj;
    const res = [];
    const TEXT_COLOR = '#00866c';
    const TEXT_HEIGHT = 12;
    sliderArr.forEach(item => {
      const { width, height, voiceArr } = item;
      const canvasWidth = Math.max(1, width);
      const canvas = new OffscreenCanvas(canvasWidth, height);
      const ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, width, height);
      voiceArr.forEach(item1 => {
        const { txt, left } = item1;
        ctx.font = '12px Arial';
        ctx.fillStyle = TEXT_COLOR;
        ctx.fillText(txt, left, TEXT_HEIGHT);
      });
      res.push(canvas.transferToImageBitmap());
    });
    return res;
  }
  onmessage = e => {
    Object.assign(configObj, e.data);
    postMessage(calcText());
  };
};
let code3 = workerCode3.toString();
code3 = code3.substring(code3.indexOf('{') + 1, code3.lastIndexOf('}'));
const blob3 = new Blob([code3], { type: 'application/javascript' });
export const calcText = URL.createObjectURL(blob3);
